import lodash from 'lodash'

class TreeUtils {
	/**
	 * 数组转树形结构
	 * @param items
	 * @param rootId
	 * @param converter
	 * @param idKey
	 * @param parentIdKey
	 * @param childrenKey
	 */
	arrayToTree = <T, TR>(
		items: T[],
		rootId: any,
		converter: (source: T) => TR = (source: T): TR => source as unknown as TR,
		idKey: string = 'id',
		parentIdKey: string = 'parentId',
		childrenKey: string = 'children',
	): TR[] => {
		// 1. 使用 lodash 的 groupBy 按 parentId 分组
		const grouped = lodash.groupBy(items, parentIdKey)

		// 2. 递归函数来构建树
		function buildTree(items: lodash.Dictionary<T[]>, parentId: any): TR[] {
			const index: string = parentId
			return lodash.map(items[index], item => {
				// @ts-ignore
				const childId = item[idKey] as string
				const children = buildTree(items, childId)

				const destItem = converter(item)

				if (children.length > 0) {
					return { ...destItem, [childrenKey]: children }
				}
				return destItem
			})
		}

		// 3. 从根节点（parentId 为 null）开始构建树
		return buildTree(grouped, rootId)
	}

	// 树形数据结构转数组
	toArray = <T, TR>(
		tree: T[],
		converter: (node: T, parentNode?: T) => TR,
		parentNode?: T,
		childrenName: string = 'children',
	): TR[] => {
		const values: TR[] = []
		const callback = (node: T, parentNode?: T): void => {
			// 转换当前节点的值
			const nodeTR: TR = converter(node, parentNode)
			// 将当前节点的值添加到结果数组中
			values.push(nodeTR)
		}
		this.traverseTree(tree, callback, parentNode, childrenName)

		return values
	}

	// 遍历树形数据结构
	traverseTree = <T>(
		tree: T[],
		callback: (node: T, parentNode?: T) => void,
		parentNode?: T,
		childrenName: string = 'children',
	): void => {
		//  map 方法遍历树中的每个节点
		tree.map(node => {
			// 将当前节点的值添加到结果数组中
			callback(node, parentNode)

			// 如果节点有子节点，递归地将子节点转换为数组并添加到结果数组中

			// @ts-ignore
			const children: T[] = node[childrenName]
			if (children) {
				this.traverseTree(children, callback, node, childrenName)
			}
		})
	}
}

const treeUtils = new TreeUtils()

export default treeUtils
